package com.wei.czz.framework.blog.helper;

import com.wei.czz.common.constant.RedisConstant;
import com.wei.czz.common.utils.CopyUtils;
import com.wei.czz.common.utils.RandomNumUtils;
import com.wei.czz.framework.blog.entity.TagEntity;
import com.wei.czz.framework.blog.service.TagService;
import com.wei.czz.framework.common.handler.ThrottleHandler;
import com.wei.czz.framework.common.handler.redis.RedisHandler;
import com.wei.czz.framework.common.handler.redis.RedisStringHandler;
import lombok.AllArgsConstructor;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2025-02-19 22:09:27
 * className: TagHelper
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class TagHelper {

    private static final Logger log = LoggerFactory.getLogger(TagHelper.class);

    private final TagService tagService;

    private final RedissonClient redissonClient;

    private final RedisHandler redisHandler;

    private final RedisStringHandler redisStringHandler;

    private final ThrottleHandler throttleHandler;

    public List<String> getTagList() {

        String redisKey = RedisConstant.STRING + RedisConstant.ALL_TAG_LIST;
        // 查询Redis缓存，获取标签列表缓存
        List<String> tagNameList = redisStringHandler.get(redisKey);
        if (Objects.nonNull(tagNameList)) {
            log.info("从缓存中获取到所有博客标签名称列表");
            throttleHandler.throttleRun(() -> {
                // 尝试更新缓存键的过期时间
                redisHandler.tryUpdateKeyExpire(redisKey, 150, RandomNumUtils.random5Minutes(10));
            }, redisKey, 1500, TimeUnit.MILLISECONDS);
            return tagNameList;
        }

        String lockKey = RedisConstant.LOCK + redisKey + RedisConstant.SPLIT + ThreadLocalRandom.current().nextInt(3);
        // 获取Redis分布式锁对象
        RLock lock = redissonClient.getLock(lockKey);
        // 加锁
        lock.lock();
        try {
            // double check
            tagNameList = redisStringHandler.get(redisKey);
            if (Objects.nonNull(tagNameList)) {
                log.info("double check 从缓存中获取到博客标签名称列表");
                return tagNameList;
            }

            /*
                获取系统所有标签
             */
            List<TagEntity> _tagList = tagService.getList();
            if (CollectionUtils.isEmpty(_tagList)) {
                tagNameList = Collections.emptyList();
                // 缓存空列表
                redisStringHandler.set(redisKey, tagNameList, RandomNumUtils.random5Minutes(10), TimeUnit.SECONDS);

                return tagNameList;
            }
            // 列表映射
            tagNameList = CopyUtils.mapList(_tagList, TagEntity::getName);

            // 缓存
            redisStringHandler.set(redisKey, tagNameList, RandomNumUtils.random5Minutes(10), TimeUnit.SECONDS);

            return tagNameList;

        } finally {
            if (lock.isLocked() && lock.isHeldByCurrentThread()) {
                // 解锁
                lock.unlock();
            }
        }
    }
}
